package com.dgut.Config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.MimeTypeUtils;
import com.dgut.Filter.JwtFilter;
import com.dgut.Filter.RestAuthenticationFilter;
import com.dgut.service.CustomUserDetailService;

import java.util.HashMap;

@Configuration
@Order(value = 99)
//@EnableWebSecurity(debug = true)
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    //@Autowired
    //PasswordEncoder passwordEncoder;

    @Autowired
    JwtFilter jwtFilter;

    @Autowired
    CustomUserDetailService userDetailService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService);
        //String password = passwordEncoder().encode("123456");
        // 用户信息存储在内存中
        //auth.inMemoryAuthentication()
                //.withUser("user")
                ////.password("123456")
                //.password(password)
                //.authorities("ROLE_ADMIN");
                //.authorities("ADMIN");
    }

    @Bean
    BCryptPasswordEncoder passwordEncoder(){
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.requestMatchers()
                //.antMatchers("/authorize/**","/api/**", "/test/**")  //拦截相关请求
                //.antMatchers("/authorize/**")  //拦截相关请求
                .antMatchers("/**")
                .and()
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterAt(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) //无状态的session管理
                .and()
                .csrf().disable()
                //.cors()
                //.and()
                .authorizeRequests()    //认证请求
                .antMatchers("admin/**","/authorize/**", "/myapi/**", "/handInfo").permitAll()   //放行登录请求入口
                .anyRequest().authenticated()   //所有进入应用的HTTP请求都要进行认证
                .and()
                .exceptionHandling().authenticationEntryPoint((res, resp, exception)->{
                    HashMap map = new HashMap();
                    map.put("status", 10003);
                    map.put("message",exception.getMessage());
                    ObjectMapper objectMapper = new ObjectMapper();
                    resp.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
                    resp.setCharacterEncoding("UTF-8");
                    resp.getWriter().write(objectMapper.writeValueAsString(map));
        })
                .and()
                .formLogin().disable()
                .httpBasic().disable();



        //添加restAuthenticationFilter到过滤器链
        //http.addFilterAt()

        //http.formLogin()// 表单认证
        //        .loginPage("/login")
        //        .usernameParameter("user")
        //        .passwordParameter("pwd")
        //        .loginProcessingUrl("/login/form")
                //.successHandler((req,resp,auth)->{
                //    //当认证成功后，响应 JSON 数据给前端
                //    HashMap map = new HashMap();
                //    map.put("status", 200);
                //    map.put("message", "success");
                //    ObjectMapper objectMapper = new ObjectMapper();
                //    resp.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
                //    resp.getWriter().write(objectMapper.writeValueAsString(map));
                //})
                //.failureHandler(((req, resp, exception) -> {
                //    //当认证失败后，响应 JSON 数据给前端
                //    HashMap map = new HashMap();
                //    map.put("status", 10001);
                //    map.put("message", exception.getMessage());
                //    ObjectMapper objectMapper = new ObjectMapper();
                //    resp.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
                //    resp.setCharacterEncoding("UTF-8");
                //    resp.getWriter().write(objectMapper.writeValueAsString(map));
                //}))
        //http.addFilterAt(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
        //        .csrf().disable()
        //        //.and()
        //        //.formLogin()
        //        //.loginPage("/login")
        //        //.and()
        //        .authorizeRequests()    //认证请求
        //        //.antMatchers("/login").permitAll() //登录请求放行
        //        .antMatchers("/authorize/**").permitAll()
        //        .anyRequest().authenticated();  //所有进入应用的HTTP请求都要进行认证
        //        //.and().logout().logoutUrl("/perform_logout")   //退出登录
        //        //.and().rememberMe();    //添加记住我功能
        //        //.and().csrf().disable();    // 关闭CSRF

        // 采⽤basic认证，体现在⽹⻚就是弹框
        //http.httpBasic()
        //        .and()
        //        .authorizeRequests()
        //        .anyRequest().authenticated();
    }

    @Autowired
    private ObjectMapper objectMapper;

    RestAuthenticationFilter restAuthenticationFilter() throws Exception {
        RestAuthenticationFilter filter = new RestAuthenticationFilter(objectMapper);
        filter.setAuthenticationSuccessHandler((req, resp, auth)->{
            //当认证成功后，响应 JSON 数据给前端
            HashMap map = new HashMap();
            map.put("status", 200);
            map.put("message", "success");
            map.put("data", auth);
            ObjectMapper objectMapper = new ObjectMapper();
            resp.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
            resp.getWriter().write(objectMapper.writeValueAsString(map));
        });
        filter.setAuthenticationFailureHandler((res,resp,exception)->{
            //当认证失败后，响应 JSON 数据给前端
            HashMap map = new HashMap();
            map.put("status", 10001);
            map.put("message", exception.getMessage());
            ObjectMapper objectMapper = new ObjectMapper();
            resp.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
            resp.setCharacterEncoding("UTF-8");
            resp.getWriter().write(objectMapper.writeValueAsString(map));
        });
        //需要设置认证管理器
        filter.setAuthenticationManager(authenticationManager());
        //拦截器拦截的地址
        filter.setFilterProcessesUrl("/authorize/login");
        return filter;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //过滤掉静态资源
        web.ignoring().antMatchers("/error/**");
    }

    //@Bean
    //@Override
    //public AuthenticationManager authenticationManager() throws Exception {
    //    return super.authenticationManagerBean();
    //}

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
